import {
  Fog,
  Group,
  MeshBasicMaterial,
  DirectionalLight,
  AmbientLight,
  PointLight,
  Vector3,
  MeshLambertMaterial,
  LineBasicMaterial,
  Color,
  MeshStandardMaterial,
  PlaneGeometry,
  Mesh,
  DoubleSide,
  RepeatWrapping,
  SRGBColorSpace,
  AdditiveBlending,
  VideoTexture,
  NearestFilter,
  BoxGeometry,
  TubeGeometry,
  QuadraticBezierCurve3,
  PointsMaterial,
  Sprite,
  SpriteMaterial,
  CustomBlending,
  AddEquation,
  DstColorFactor,
  OneFactor,
  TextureLoader,
  sRGBEncoding,
  Box3,
  ShaderMaterial,
  FrontSide,
  CylinderGeometry,
} from "three";
import {
  Mini3d,
  ExtrudeMap,
  BaseMap,
  Line,
  Grid,
  Label3d,
  Plane,
  Particles,
  GradientShader,
  DiffuseShader,
  Focus,
  createHistory,
  random,
} from "@/mini3d";
import useCoord from "@/hooks/useCoord.js";
import useSequenceFrameAnimate from "@/hooks/useSequenceFrameAnimate";
import { geoMercator } from "d3-geo";
const { getBoundingBox } = useCoord();
// import labelIcon from "@/assets/texture/label-icon.png"
import chinaData from "./map/chinaData";
import _provincesData from "./map/provincesData";
import scatterData from "./map/scatter";
import infoData from "./map/infoData";
import gsap from "gsap";
import emitter from "@/utils/emitter";

import { InteractionManager } from "three.interactive";
import { ChildMap } from "./map-china-child";
// 序列帧
const { createSequenceFrame } = useSequenceFrameAnimate();
function sortByValue(data) {
  data.sort((a, b) => b.value - a.value);
  return data;
}
export class World extends Mini3d {
  constructor(
    canvas,
    assets,
    provincesData,
    callBackSelProvince,
    getProvinceBox,
    showTable,
    hideTable,
    play
  ) {
    super(canvas, assets);
    this.currentScene = "mainScene"; // 当前场景 mainScene | childScene
    this.clicked = false; // 是否已经点击
    this.play = play;
    this.returnBtn = document.querySelector(".return-btn");
    this.callBackSelProvince = callBackSelProvince;
    this.showTable = showTable;
    this.hideTable = hideTable;
    this.getProvinceBox = getProvinceBox;
    this.provincesData = [];
    this.currentProviceMap = 0;
    this.selectProvinceTimer = null;

    
    // 双击检测变量
    this.clickTimeout = null;
    this.clickCount = 0;
    this.doubleClickDelay = 300; // 双击间隔时间(ms)

    // 子集数据
    this.childGeoData = [];
    // 中心坐标

    this.history = new createHistory();
    this.history.push({ name: "中国" });
    // this.geoProjectionCenter = [113.280637, 23.125178]
    this.geoProjectionCenter = [105.892151, 38.676493];

    // 缩放比例
    // this.geoProjectionScale = 120
    this.geoProjectionScale = 20;
    // 飞线中心
    // this.flyLineCenter =  [113.544372, 23.329249]
    this.flyLineCenter = [115.732975, 27.636112]; //江西省
    // 地图拉伸高度
    this.depth = 0.5;
    // this.mapFocusLabelInfo = {
    //   name: "广东省",
    //   enName: "GUANGDONG PROVINCE",
    //   center: [113.280637, 20.625178],
    // }
    this.mapFocusLabelInfo = {
      name: "",
      enName: "",
      center: [113.280637, 20.625178],
    };

    // 雾
    // this.scene.fog = new Fog(0x102736, 1, 50)
    //加载背景图
    const textureLoader = new TextureLoader();
    const texture = textureLoader.load(
      "https://cdn.lingshan.jxyunge.com/20250505/5a4052ed-e068-4572-b817-d8a7dd523498.png",
      // 可选：加载完成后的回调
      (texture) => {
        texture.encoding = sRGBEncoding;
        texture.colorSpace = SRGBColorSpace;
      },
      // 可选：加载进度回调
      (progress) => {
        console.log(
          "加载进度:",
          (progress.loaded / progress.total) * 100 + "%"
        );
      },
      // 可选：加载错误回调
      (error) => {
        console.error("加载失败:", error);
      }
    );

    // 背景
    // this.scene.background = new Color(0x102736)
    this.scene.background = texture;

    // 相机初始位置
    this.camera.instance.position.set(
      -13.767695123014105,
      12.990152163077308,
      39.28228164159694
    );
    this.camera.instance.near = 1;
    this.camera.instance.far = 10000;
    this.camera.instance.updateProjectionMatrix();

    // 在相机初始化后添加限制
    this.camera.controls.minPolarAngle = Math.PI / 6; // 30度
    this.camera.controls.maxPolarAngle = Math.PI / 2.5; // 72度
    // 创建交互管理
    this.interactionManager = new InteractionManager(
      this.renderer.instance,
      this.camera.instance,
      this.canvas
    );

    this.assets = assets;
    // 创建环境光
    this.initEnvironment();
    this.init();
  }

  // 初始化粒子
  initParticle = (scene, bound) => {
    // 获取中心点和中间地图大小
    let { center, size } = bound;
    // 构建范围，中间地图的2倍
    let minX = center.x - size.x;
    let maxX = center.x + size.x;
    // let minY = center.y - size.y
    // let maxY = center.y + size.y

    let minY = -6;
    let maxY = 6;
    // let minZ = this.depth + 0.5; // 从地图上方开始
    // let maxZ = this.depth + 2;   // 飞升到一定高度
    let minZ = center.z - size.z; // 从地图上方开始
    let maxZ = center.z + size.z; // 飞升到一定高度

    let particleArr = [];
    for (let i = 0; i < 6; i++) {
      const particle = createSequenceFrame({
        image:
          "https://cdn.lingshan.jxyunge.com/20250512/026fe4f7-c60a-4177-a611-7a8499502a9b.png",
        width: 380,
        height: 400,
        frame: 9,
        column: 9,
        row: 1,
        speed: 0.5,
      });
      let particleScale = random(5, 10) / 1000;
      particle.scale.set(particleScale, particleScale, particleScale);
      // particle.rotation.x = Math.PI / 2
      particle.rotation.set(0, 0, 0);
      let x = random(minX, maxX);
      let y = random(minY, maxY);
      let z = random(minZ, maxZ);
      particle.position.set(x, y, z);
      particleArr.push(particle);
    }

    this.scene.add(...particleArr);

    return particleArr;
  };
  getMapDataForChild(userData, callback) {
    let url = `https://geo.datav.aliyun.com/areas_v3/bound/${userData.adcode}_full.json`;

    if (userData.childrenNum === 0) {
      url = `https://geo.datav.aliyun.com/areas_v3/bound/${userData.adcode}.json`;
    }
    fetch(url)
      .then((res) => {
        return res.text();
      })
      .then((res) => {
        callback && callback(res);
      });
  }

  calcUv2(geometry, width, height, minX, minY) {
    const positionAttribute = geometry.attributes.position;
    const uvAttribute = geometry.attributes.uv;

    const count = geometry.groups[0].count;
    for (let i = 0; i < count; i++) {
      const x = positionAttribute.getX(i);
      const y = positionAttribute.getY(i);

      const u = (x - minX) / width;
      const v = (y - minY) / height;

      uvAttribute.setXY(i, u, v);
    }

    uvAttribute.needsUpdate = true;
    geometry.computeVertexNormals();
  }
  /**
   * 设置css3d标签的隐藏显示
   * @param {*} labelGroup
   * @param {*} bool
   */
  setLabelVisible(labelGroup = "labelGroup", bool) {
    this[labelGroup].visible = bool;
    this[labelGroup].children.map((label) => {
      bool ? label.show() : label.hide();
    });
  }
  // 隐藏显示主地图及标签
  setMainMapVisible(bool) {
    this.scene.getObjectByName("chinaMapGroup").visible = bool;
    this.mapGroup.visible = bool;
    this.flyLineFocusGroup.visible = bool;
    this.allGuangquan.forEach(group => {
        group.visible = bool;
    });
    this.barGroup.visible = bool;
    this.quanGroup.visible = bool;
    if (bool === false) {
      this.scene.remove(this.barGroup);
      this.scene.remove(this.flyLineFocusGroup);
    } else {
      this.scene.add(this.barGroup);
      this.scene.add(this.flyLineFocusGroup);

      localStorage.setItem("baseScale","")
      this.camera.instance.position.set(
        -13.767695123014105,
        12.990152163077308,
        39.28228164159694
      );
      this.camera.instance.near = 1;
      this.camera.instance.far = 10000;
      this.camera.instance.updateProjectionMatrix();
      let target = this.scene.getObjectByName("chinaMapGroup").position;
      // 动画过渡到新位置
      // modify by LING:一级地图位置调整
      gsap.to(this.camera.instance.position, {
        // x: -0.17427287762525134,
        // y: 13.678992786206543,
        // z: 20.688611202093714,
        x: 1.5396690226661434,
        y: 19.148706062115334,
        z: 10.831154437245264,
        duration: 1.5,
        ease: "power2.out",
        onUpdate: () => {
          this.camera.controls.target.copy(target);
          this.camera.controls.update();
        },
      });
    }
  }
  disposeObject = (obj) => {
    if (obj.isMesh) {
      if (obj.geometry) {
        obj.geometry.dispose(); // 释放几何体
      }
      if (obj.material) {
        if (Array.isArray(obj.material)) {
          obj.material.forEach((m) => m.dispose()); // 处理材质数组
        } else {
          obj.material.dispose(); // 释放单一材质
        }
      }
    }
    // 清理自定义数据或事件监听
    if (obj.userData) {
      if (obj.userData.clickHandler) {
        window.removeEventListener("click", obj.userData.clickHandler);
      }
      obj.userData = null;
    }
  };
  // 新增方法：计算地理边界和缩放比例
  calcGeoBounds(features) {
    let minLng = Infinity,
      maxLng = -Infinity,
      minLat = Infinity,
      maxLat = -Infinity;

    features.forEach((feature) => {
      const coordWalker = (coords) => {
        coords.forEach((item) => {
          if (Array.isArray(item)) {
            if (typeof item[0] === "number" && typeof item[1] === "number") {
              // 有效坐标点
              const [lng, lat] = item;
              minLng = Math.min(minLng, lng);
              maxLng = Math.max(maxLng, lng);
              minLat = Math.min(minLat, lat);
              maxLat = Math.max(maxLat, lat);
            } else {
              // 递归处理嵌套数组
              coordWalker(item);
            }
          }
        });
      };

      // 初始化遍历坐标
      coordWalker(feature.geometry.coordinates);
    });

    return { minLng, maxLng, minLat, maxLat };
  }

  // 新增方法：自动计算缩放比例
  // calcAutoScale(bounds, viewportSize = 15) {

  //   // 根据边界宽高比动态计算
  //   const mapAspect = bounds.width / bounds.height;
  //   const scaleX = viewportSize / bounds.width;
  //   const scaleY = viewportSize / bounds.height;
  //   console.log("计算======")
  //   console.log(bounds)
  //   console.log(scaleX)
  //   console.log(scaleY)
  //   return Math.min(scaleX, scaleY) * 0.8; // 保留10%边距
  // }
  calcAutoScale(bounds, viewportSize = 15) {
    // 有效性校验
    if (
      !bounds ||
      bounds.maxLng <= bounds.minLng ||
      bounds.maxLat <= bounds.minLat
    ) {
      console.error("无效的边界参数", bounds);
      return 1; // 返回安全值
    }

    // 创建临时投影（保持与主投影一致）
    const projection = geoMercator()
      .center([
        (bounds.minLng + bounds.maxLng) / 2,
        (bounds.minLat + bounds.maxLat) / 2,
      ])
      .translate([0, 0])
      .scale(1); // 基础比例

    // 转换边界坐标
    const coordinates = [
      [bounds.minLng, bounds.maxLat], // 左上
      [bounds.maxLng, bounds.minLat], // 右下
    ].map((coord) => {
      const p = projection(coord);
      return p ? p : [0, 0]; // 容错处理
    });

    // 计算实际投影尺寸
    const mapWidth = coordinates[1][0] - coordinates[0][0];
    const mapHeight = coordinates[0][1] - coordinates[1][1]; // 注意y轴方向

    // 防止除以零
    if (mapWidth <= 0 || mapHeight <= 0) {
      console.warn("无效的投影尺寸", mapWidth, mapHeight);
      return 1;
    }

    // 动态计算缩放比例
    const scaleX = viewportSize / mapWidth;
    const scaleY = viewportSize / mapHeight;
    const finalScale = Math.min(scaleX, scaleY) * 0.8; // 保留边距

    console.log("最终缩放比例:", finalScale);
    return finalScale;
  }

  calculateCameraPosition(bounds3D, paddingFactor = 1.5) {
    const boxSize = new Vector3();
    bounds3D.getSize(boxSize);

    // 计算最佳观测距离
    const maxDimension = Math.max(boxSize.x, boxSize.y, boxSize.z);
    const distance = maxDimension * paddingFactor;

    // 获取中心点坐标
    const center = new Vector3();
    bounds3D.getCenter(center);
    
    // modify by LING: 更改下钻地图视角,四级地图俯视角度需更大一点
    let position = new Vector3();
    if(this.childMap.areaData.length > 1) {
      position = new Vector3(
        center.x - distance * 0.7,
        center.y + distance * 0.5,
        center.z + distance * 0.5
      );
    } else {
      position = new Vector3(
        center.x - distance * 0.1,
        center.y + distance * 0.9,
        center.z + distance * 0.5
      )
    }

    // 默认观测角度（俯视角度）
    return {
      position: position,
      target: center,
    };
  }
  toggleAllGroupVisible(isVisible) {
    this.allBar.visible = isVisible;
    this.allBarMaterial.visible = isVisible;
    this.allGuangquan.visible = isVisible;
    this.allProvinceLabel.visible = isVisible;
    this.allProvinceNameLabel.visible = isVisible;
    // 隐藏飞线=====
    this.flyLineGroup.visible = isVisible;
    // 隐藏bar label
    this.barGroup.visible = isVisible;
    this.labelGroup.visible = isVisible;

    // 修改省份标签可见性
    this.allProvinceLabel.forEach((label) => {
      isVisible ? label.show() : label.hide();
    });

    // 修改城市名称标签可见性
    this.allProvinceNameLabel.forEach((label) => {
      isVisible ? label.show() : label.hide();
    });
  }
  loadChildMap(name, type = "name") {
    if (type === "name") {
      let mapJsonData = this.assets.instance.getResource("china");
      mapJsonData = JSON.parse(mapJsonData);
      let currentChildren = mapJsonData.features.filter(
        (obj) => obj.properties.name === name
      );
      if (currentChildren && currentChildren.length === 0) {
        currentChildren = this.childGeoData.features.filter(
          (obj) => obj.properties.name === name
        );
      }
      if (currentChildren && currentChildren.length > 0) {
        let userData = currentChildren[0].properties;
        this.getMapDataForChild(userData, (data) => {
          this.returnBtn.style.display = "block";
          const childGeoData = JSON.parse(data);
          this.childGeoData = childGeoData;
          const bounds = this.calcGeoBounds(childGeoData.features);
          const autoScale = this.calcAutoScale(bounds);
          this.childMap && this.childMap.destroy();
          this.childMap = new ChildMap(this, {
            adcode: userData.adcode,
            center: userData.center,
            centroid: userData.centroid,
            childrenNum: userData.childrenNum,
            mapData: data,
            geoProjectionScale: autoScale, // 传入动态计算值
            parentBoxSize: [129.00074005126953, (126.23402404785156 * 3) / 4],
          });
          this.childSceneGroup.add(this.childMap.instance);
          this.setMainMapVisible(false);
          //新增移除逻辑
          // this.scene.remove(this.flyLineFocusGroup)
          this.toggleAllGroupVisible(false);
          this.otherLabel = [];
          let childCenter = userData.center;
          this.camera.controls.reset();
          // 关键新增：等待子地图渲染完成后获取包围盒
          setTimeout(() => {
            const bbox = new Box3().setFromObject(this.childMap.instance);
            // 计算相机参数
            const { position, target } = this.calculateCameraPosition(bbox);

            // 动画过渡到新位置
            gsap.to(this.camera.instance.position, {
              x: position.x,
              y: position.y,
              z: position.z,
              duration: 1.5,
              ease: "power2.out",
              onUpdate: () => {
                this.camera.controls.target.copy(target);
                this.camera.controls.update();
              },
            });
          }, 100); // 延迟确保子地图完成渲染

          this.currentScene = "childScene";
          // this.assets.setEnable(false)
        });
      }
    }
    if (type === "userData") {
      this.getMapDataForChild(name, (data) => {
        this.returnBtn.style.display = "block";
        const childGeoData = JSON.parse(data);
        this.childGeoData = childGeoData;

        const bounds = this.calcGeoBounds(childGeoData.features);
        const autoScale = this.calcAutoScale(bounds);
        this.childMap && this.childMap.destroy();
        this.childMap = new ChildMap(this, {
          adcode: name.adcode,
          center: name.center,
          centroid: name.centroid,
          childrenNum: name.childrenNum,
          mapData: data,
          geoProjectionScale: autoScale, // 传入动态计算值
          parentBoxSize: [129.00074005126953, (126.23402404785156 * 3) / 4],
        });
        this.childSceneGroup.add(this.childMap.instance);
        this.setMainMapVisible(false);
        //新增移除逻辑
        this.scene.remove(this.flyLineFocusGroup);
        this.otherLabel = [];
        let childCenter = name.center;
        this.camera.controls.reset();
        // 关键新增：等待子地图渲染完成后获取包围盒
        setTimeout(() => {
          const bbox = new Box3().setFromObject(this.childMap.instance);
          // 计算相机参数
          const { position, target } = this.calculateCameraPosition(bbox);
          // 动画过渡到新位置
          gsap.to(this.camera.instance.position, {
            x: position.x,
            y: position.y,
            z: position.z,
            duration: 1.5,
            ease: "power2.out",
            onUpdate: () => {
              this.camera.controls.target.copy(target);
              this.camera.controls.update();
            },
          });
        }, 100); // 延迟确保子地图完成渲染

        // this.camera.instance.position
        this.currentScene = "childScene";
        // this.assets.setEnable(false)
      });
    }
  }
  getProvinceData() {
    //模拟一个8秒返回的promise函数
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(_provincesData);
      }, 8000);
    });
  }
  async init(data) {
    this.provincesData = await this.getProvinceData();
    // 标签组
    this.map = null;
    this.mapTop = null;
    this.mapLine = null;
    this.mapGroup = null;
    this.focusMapGroup = null;
    this.labelGroup = new Group();
    this.label3d = new Label3d(this);
    this.labelGroup.rotation.x = -Math.PI / 2;
    this.scene.add(this.labelGroup);
    // 飞线焦点光圈组
    this.flyLineFocusGroup = new Group();
    this.flyLineFocusGroup.visible = false;
    this.flyLineFocusGroup.rotation.x = -Math.PI / 2;
    this.scene.add(this.flyLineFocusGroup);
    // 区域事件元素
    this.eventElement = [];
    // 鼠标移上移除的材质
    this.defaultMaterial = null; // 默认材质
    this.defaultLightMaterial = null; // 高亮材质
    // 创建底部高亮
    this.createBottomBg();
    // 模糊边线
    this.createChinaBlurLine();

    // 扩散网格
    // this.createGrid()
    // 旋转圆环
    this.createRotateBorder();
    // 创建标签
    this.createLabel();
    // 创建地图
    this.createMap(data);

    // 添加事件
    this.createEvent();
    // 创建飞线
    this.createFlyLine();
    // 创建飞线焦点
    this.createFocus();
    // 创建粒子
    this.createParticles();
    // 创建散点图
    // this.createScatter()
    // 创建信息点
    // this.createInfoPoint()
    // this.loop()
    // 创建轮廓
    this.createStorke();
    // this.time.on("tick", () => {
    //   console.log(this.camera.instance.position);
    // });

    this.initRoundMap();
    // 创建动画时间线
    let tl = gsap.timeline({
      onComplete: () => {},
    });
    tl.pause();
    this.animateTl = tl;
    this.play();
    tl.addLabel("focusMap", 1.5);
    tl.addLabel("focusMapOpacity", 2);
    tl.addLabel("bar", 3);
    // modify by LING:一级地图
    window.camera = this.camera;
    tl.to(this.camera.instance.position, {
      duration: 2,
      // x: -0.17427287762525134,
      // y: 13.678992786206543,
      // z: 20.688611202093714,
      x: 1.5396690226661434,
      y: 19.148706062115334,
      z: 10.831154437245264,
      ease: "circ.out",
      onStart: () => {
        this.flyLineFocusGroup.visible = false;
      },
      onComplete: () => {
        this.camera.controls.saveState();
      },
    });
    tl.to(
      this.focusMapGroup.position,
      {
        duration: 1,
        x: 0,
        y: 0,
        z: 0,
      },
      "focusMap"
    );

    tl.to(
      this.focusMapGroup.scale,
      {
        duration: 1,
        x: 1,
        y: 1,
        z: 1,
        ease: "circ.out",
        onComplete: () => {
          this.flyLineGroup.visible = true;
          // this.scatterGroup.visible = true
          this.InfoPointGroup ? (this.InfoPointGroup.visible = true) : "";
          // this.createInfoPointLabelLoop()
        },
      },
      "focusMap"
    );

    tl.to(
      this.focusMapTopMaterial,
      {
        duration: 1,
        opacity: 1,
        ease: "circ.out",
      },
      "focusMapOpacity"
    );
    tl.to(
      this.focusMapSideMaterial,
      {
        duration: 1,
        opacity: 1,
        ease: "circ.out",
        onComplete: () => {
          this.focusMapSideMaterial.transparent = false;
        },
      },
      "focusMapOpacity"
    );
    this.otherLabel.map((item, index) => {
      let element = item.element.querySelector(".other-label");
      tl.to(
        element,
        {
          duration: 1,
          delay: 0.1 * index,
          translateY: 0,
          opacity: 1,
          ease: "circ.out",
        },
        "focusMapOpacity"
      );
    });
    tl.to(
      this.mapLineMaterial,
      {
        duration: 0.5,
        delay: 0.3,
        opacity: 1,
      },
      "focusMapOpacity"
    );
    tl.to(
      this.rotateBorder1.scale,
      {
        delay: 0.3,
        duration: 1,
        x: 1,
        y: 1,
        z: 1,
        ease: "circ.out",
      },
      "focusMapOpacity"
    );
    tl.to(
      this.rotateBorder2.scale,
      {
        duration: 1,
        delay: 0.5,
        x: 1,
        y: 1,
        z: 1,
        ease: "circ.out",
        onComplete: () => {
          this.flyLineFocusGroup.visible = true;
          emitter.$emit("mapPlayComplete");
          // 添加加载江西省地图的代码
          setTimeout(() => {
            
            this.loadChildMap("江西省");
          }, 300); // 延迟1秒执行，确保动画完全结束
        },
      },
      "focusMapOpacity"
    );
    this.allBar.map((item, index) => {
      if (item.userData.name === "广州市") {
        return false;
      }
      tl.to(
        item.scale,
        {
          duration: 1,
          delay: 0.1 * index,
          x: 1,
          y: 1,
          z: 1,
          ease: "circ.out",
        },
        "bar"
      );
    });
    this.allBarMaterial.map((item, index) => {
      tl.to(
        item,
        {
          duration: 1,
          delay: 0.1 * index,
          opacity: 1,
          ease: "circ.out",
        },
        "bar"
      );
    });

    this.allProvinceLabel.map((item, index) => {
      let element = item.element.querySelector(".provinces-label-wrap");
      let number = item.element.querySelector(".number .value");
      let numberVal = Number(number.innerText);
      let numberAnimate = {
        score: 0,
      };
      tl.to(
        element,
        {
          duration: 1,
          delay: 0.2 * index,
          translateY: 0,
          opacity: 1,
          ease: "circ.out",
        },
        "bar"
      );
      tl.to(
        numberAnimate,
        {
          duration: 1,
          delay: 0.2 * index,
          score: numberVal,
          onUpdate: showScore,
        },
        "bar"
      );
      function showScore() {
        number.innerText = numberAnimate.score.toFixed(0);
      }
    });
    this.allProvinceNameLabel.map((item, index) => {
      let element = item.element.querySelector(".provinces-name-label-wrap");

      tl.add(
        gsap.to(element, {
          duration: 0.5,
          delay: 0.05 * index,
          translateY: 0,
          opacity: 1,
          ease: "circ.out",
        }),
        "bar"
      );
    });
    this.allGuangquan.map((item, index) => {
      tl.to(
        item.children[0].scale,
        {
          duration: 1,
          delay: 0.1 * index,
          x: 1,
          y: 1,
          z: 1,
          ease: "circ.out",
        },
        "bar"
      );
      tl.to(
        item.children[1].scale,
        {
          duration: 1,
          delay: 0.1 * index,
          x: 1,
          y: 1,
          z: 1,
          ease: "circ.out",
        },
        "bar"
      );
    });
    // setTimeout(()=>{
    //   this.loadChildMap("江西省")
    // },300)

    // 动画完成后模拟鼠标拖动旋转
    // setTimeout(() => {
    //   const targetRotation = Math.PI / 4; // 目标角度（45度倾斜）
    //   const currentRotation = this.camera.instance.rotation.x;
    //   const duration = 2; // 动画时长（秒）

    //   // 使用 gsap 平滑过渡 camera 位置
    //   gsap.to(this.camera.instance.position, {
    //     x: this.camera.instance.position.x,
    //     y: this.camera.instance.position.y * 1.5, // 提高 Y 值，模拟视角倾斜
    //     z: this.camera.instance.position.z * 0.7, // 调整 Z 值，使视角更倾斜
    //     duration: duration,
    //     ease: "power2.out",
    //     onUpdate: () => {
    //       // 手动调整 camera 的 rotation.x
    //       this.camera.instance.rotation.x = gsap.utils.interpolate(
    //         currentRotation,
    //         targetRotation,
    //         this.camera.instance.position.y / (this.camera.instance.position.y * 1.5)
    //       );
    //       this.camera.controls.update();
    //     },
    //     onComplete: () => {
    //       // 确保最终角度正确
    //       this.camera.instance.rotation.x = -targetRotation;
    //       this.camera.controls.update();
    //     }
    //   });
    // }, 300); // 延迟 3 秒执行
  }
  move(mesh) {
    mesh.traverse((obj) => {
      if (obj.isMesh) {
        obj.material = this.defaultLightMaterial;
      }
    });
  }
  initRoundMap() {
    this.currentProviceMap++;
    // this.selectProvinceTimer = setInterval(() => {
    //   let currentProviceMap = this.provincesData[this.currentProviceMap];
    //   this.map.coordinates.forEach((item, index) => {
    //     if (item.name == currentProviceMap.name) {
    //       this.map.mapGroup.children[index].userData.name =
    //         currentProviceMap.name;
    //       this.move(this.map.mapGroup.children[index]);
    //     }
    //   });
    //   // this.map.mapGroup.children
    // }, 3000);
    this.callBackSelProvince(this.map);
  }

  initEnvironment() {
    let sun = new AmbientLight(0x194f8f, 1);
    this.scene.add(sun);
    // let directionalLight = new DirectionalLight(0xfffff, 1)
    // directionalLight.position.set(-30, 6, -8)

    // 修改方向光颜色和强度
    let directionalLight = new DirectionalLight(0xffffff, 2.5); // 增强光照强度
    // directionalLight.position.set(-30, 15, -8) // 调整光源高度

    directionalLight.position.set(-10, 20, 10); // 更合理的位置
    directionalLight.castShadow = true;

    // 阴影设置
    directionalLight.shadow.mapSize.width = 2048;
    directionalLight.shadow.mapSize.height = 2048;
    directionalLight.shadow.camera.near = 0.5;
    directionalLight.shadow.camera.far = 500;
    directionalLight.shadow.camera.left = -50;
    directionalLight.shadow.camera.right = 50;
    directionalLight.shadow.camera.top = 50;
    directionalLight.shadow.camera.bottom = -50;

    this.scene.add(directionalLight);

    // 3. 补光 - 使用不同的角度和颜色
    const fillLight = new DirectionalLight(0x194f8f, 0.6);
    fillLight.position.set(10, 10, -10);
    this.scene.add(fillLight);

    // 4. 可选 - 添加点光源作为补充
    const pointLight = new PointLight(0x194f8f, 1, 100);
    pointLight.position.set(0, 10, 0);
    this.scene.add(pointLight);

    //聚点光源调节大点
    // this.createPointLight({
    //   color: "#184a8a ",
    //   intensity: 800,
    //   distance: 10000,
    //   x: -9,
    //   y: 3,
    //   z: -3,
    // })
    // this.createPointLight({
    //   color: "#184a8a ",
    //   intensity: 200,
    //   distance: 10000,
    //   x: 0,
    //   y: 2,
    //   z: 5,
    // })
  }
  consoleCameraPosition() {
    // console.log(this.camera.position)
  }
  createPointLight(pointParams) {
    const pointLight = new PointLight(
      0x50c2ff,
      pointParams.intensity,
      pointParams.distance
    );
    pointLight.position.set(pointParams.x, pointParams.y, pointParams.z);
    this.scene.add(pointLight);
  }
  loop() {
    this.animationStop = window.requestAnimationFrame(() => {
      this.loop();
    });
    // 粒子上升
    if (this.particleArr.length) {
      for (let i = 0; i < this.particleArr.length; i++) {
        this.particleArr[i].updateSequenceFrame();
        this.particleArr[i].position.y += 0.2;
        if (this.particleArr[i].position.y >= 6) {
          this.particleArr[i].position.y = -6;
        }
      }
    }
  }
  createMap(data) {
    let mapGroup = new Group();
    mapGroup.name = "chinaMapGroup";
    this.mapGroup = mapGroup;
    this.focusMapGroup = new Group();
    this.sceneGroup = new Group();
    let { china, chinaTopLine } = this.createChina(data);
    let { map, mapTop, mapLine } = this.createProvince(data);

    this.map = map;
    this.mapTop = mapTop;
    this.mapLine = mapLine;
    china.setParent(this.mapGroup);
    chinaTopLine.setParent(this.mapGroup);
    // 创建扩散
    // this.createDiffuse()
    this.map.setParent(this.focusMapGroup);
    this.mapTop.setParent(this.focusMapGroup);
    this.mapLine.setParent(this.focusMapGroup);
    this.focusMapGroup.position.set(0, 0, -0.01);
    this.focusMapGroup.scale.set(1, 1, 0);
    this.mapGroup.add(this.focusMapGroup);
    this.mapGroup.rotation.x = -Math.PI / 2;
    this.mapGroup.position.set(0, 0.2, 0);
    

    this.childSceneGroup = new Group();
    this.sceneGroup.add(this.mapGroup, this.childSceneGroup);
    let earthGroupBound = getBoundingBox(this.sceneGroup);
    this.scene.add(this.sceneGroup);

    this.particleArr = this.initParticle(this.scene, earthGroupBound);
    this.loop();
    this.createBar();
  }
  createChina(data) {
    let params = {
      chinaBgMaterialColor: "#4288C7", //底部中国地图省份分割线
      lineColor: "#4288C7",
    };
    let chinaData = data || this.assets.instance.getResource("china");
    let chinaBgMaterial = new MeshLambertMaterial({
      color: new Color(params.chinaBgMaterialColor),
      transparent: true,
      opacity: 1,
    });
    let china = new BaseMap(this, {
      //position: new Vector3(0, 0, -0.03),
      data: chinaData,
      geoProjectionCenter: this.geoProjectionCenter,
      geoProjectionScale: this.geoProjectionScale,
      merge: true,
      material: chinaBgMaterial,
      renderOrder: 2,
    });
    let glowLineMaterial = new ShaderMaterial({
      uniforms: {
        glowColor: { value: new Color(0x4bc2f2) }, // 发光蓝
        viewVector: { value: this.camera.instance.position },
      },
      vertexShader: `
        uniform vec3 viewVector;
        varying float intensity;
        void main() {
          vec3 vNormal = normalize(normalMatrix * normal);
          vec3 vNormView = normalize(normalMatrix * viewVector);
          intensity = pow( dot(vNormal, vNormView), 2.0 );
  
          gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
        }
      `,
      fragmentShader: `
        uniform vec3 glowColor;
        varying float intensity;
        void main() {
          float alpha = intensity;
          gl_FragColor = vec4(glowColor, alpha);
        }
      `,
      side: FrontSide,
      blending: AdditiveBlending,
      transparent: true,
      depthWrite: false,
    });
    let chinaTopLineMaterial = new LineBasicMaterial({
      color: params.lineColor,
    });
    let chinaTopLine = new Line(this, {
      // position: new Vector3(0, 0, -0.02),
      data: chinaData,
      geoProjectionCenter: this.geoProjectionCenter,
      geoProjectionScale: this.geoProjectionScale,
      material: chinaTopLineMaterial,
      // material:glowLineMaterial,
      renderOrder: 3,
    });
    chinaTopLine.lineGroup.position.z += 0.01;
    return { china, chinaTopLine };
  }

  createGlowLineMaterial() {
    return new ShaderMaterial({
      uniforms: {
        glowColor: { value: new Color(0x4bc2f2) },
        intensity: { value: 1.0 },
        lineWidth: { value: 0.02 }, // 发光线宽，0.02 可调
      },
      vertexShader: `  
        uniform float lineWidth;  
        varying vec3 vPosition;  
  
        void main() {  
          vPosition = position;  
          
          // 拉宽线条坐标实现光晕扩散  
          vec4 mvPosition = modelViewMatrix * vec4(position, 1.0);  
          
          // 这里简单拉开顶点，让线条变宽实现光晕（需Geo配合）  
          // 实际可能用Extrude或tube实现，示意  
          
          gl_Position = projectionMatrix * mvPosition;  
        }  
      `,
      fragmentShader: `  
        uniform vec3 glowColor;  
        uniform float intensity;  
        varying vec3 vPosition;  
  
        void main() {  
          // 计算离中心或边界的虚拟距离，这里简单用位置模拟柔和发光  
          float dist = length(vPosition.xy);  
  
          // 生成发光强度渐变，离边界越近越亮  
          float glow = smoothstep(0.05, 0.0, dist);  
  
          glow *= intensity;  
  
          gl_FragColor = vec4(glowColor * glow, glow);  
        }  
      `,
      transparent: true,
      blending: AdditiveBlending,
      depthWrite: false,
      side: DoubleSide,
    });
  }
  createChinaWithGlow(data) {
    let chinaData = data || this.assets.instance.getResource("china");

    // 地图填充材质保持原有
    let chinaBgMaterial = new THREE.MeshLambertMaterial({
      color: new THREE.Color("#194f8f"),
      transparent: true,
      opacity: 1,
    });
    let china = new BaseMap(this, {
      data: chinaData,
      geoProjectionCenter: this.geoProjectionCenter,
      geoProjectionScale: this.geoProjectionScale,
      merge: true,
      material: chinaBgMaterial,
      renderOrder: 2,
    });

    // 用自定义发光 ShaderMaterial 代替原来 chinaTopLineMaterial
    let chinaTopLineMaterial = createGlowLineMaterial();

    let chinaTopLine = new Line(this, {
      data: chinaData,
      geoProjectionCenter: this.geoProjectionCenter,
      geoProjectionScale: this.geoProjectionScale,
      material: chinaTopLineMaterial,
      renderOrder: 3,
    });

    chinaTopLine.lineGroup.position.z += 0.01;

    return { china, chinaTopLine };
  }
  // 返回上一级
  goBack() {
    this.history.undo();

    if (!this.history.getIndex()) {
      this.currentScene = "mainScene";
      this.returnBtn.style.display = "none";
      this.childMap && this.childMap.destroy();
      this.childMap = null;
      this.setMainMapVisible(true);
      this.toggleAllGroupVisible(true);
    } else {
      let userData = this.history.present;
      if (userData?.center) {
        this.loadChildMap(userData, "userData");
      } else {
        this.loadChildMap(userData.name, "name");
      }
    }

    this.camera.controls.reset();
  }

  createProvince(dataJson) {
    let mapJsonData = dataJson || this.assets.instance.getResource("china");
    let [topMaterial, sideMaterial] = this.createProvinceMaterial();

    this.focusMapTopMaterial = topMaterial;
    this.focusMapSideMaterial = sideMaterial;
    // let glowLineMaterial = new ShaderMaterial({
    //   uniforms: {
    //     glowColor: { value: new Color(0xcd210f) }, // 发光蓝
    //     viewVector: { value: this.camera.instance.position },
    //   },
    //   vertexShader: `
    //     uniform vec3 viewVector;
    //     varying float intensity;
    //     void main() {
    //       vec3 vNormal = normalize(normalMatrix * normal);
    //       vec3 vNormView = normalize(normalMatrix * viewVector);
    //       intensity = pow( dot(vNormal, vNormView), 2.0 );
  
    //       gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    //     }
    //   `,
    //   fragmentShader: `
    //     uniform vec3 glowColor;
    //     varying float intensity;
    //     void main() {
    //       float alpha = intensity;
    //       gl_FragColor = vec4(glowColor, alpha);
    //     }
    //   `,
    //   side: FrontSide,
    //   blending: AdditiveBlending,
    //   transparent: true,
    //   depthWrite: false,
    // });
    let map = new ExtrudeMap(this, {
      geoProjectionCenter: this.geoProjectionCenter,
      geoProjectionScale: this.geoProjectionScale,
      position: new Vector3(0, 0, 0.11),
      data: mapJsonData,
      depth: this.depth,
      topFaceMaterial: topMaterial,
      sideMaterial: sideMaterial,
      renderOrder: 9,
    });
    let faceMaterial = new MeshStandardMaterial({
      emissive: new Color(0x8ab4d9),
      emissiveIntensity: 2,
      transparent: true,
      opacity: 0.7,
      side: DoubleSide, // 确保双面可见
    });
    faceMaterial.userData = {
      isSelected: false,
      originalPosition: null,
    };

    // 创建渐变着色器时添加内发光参数
    let faceGradientShader = new GradientShader(faceMaterial, {
      uColor1: 0x194f8f,
      uColor2: 0x194f8f,
      uGlowColor: new Color(0x4bc2f2), // RGBA(75,194,242)
      uGlowRadius: 0.15, // 根据UV空间调整
      uGlowIntensity: 0.54,
    });

    // 直接修改材质着色器（确保在 GradientShader 之后）
    faceMaterial.onBeforeCompile = (shader) => {
      // 顶点着色器传递 uv
      shader.vertexShader = shader.vertexShader.replace(
        "void main() {",
        `
        varying vec2 vUv;
        void main() {
          vUv = uv;
        `
      );

      // 片元着色器添加 uniform 和 varying，放在全局声明区
      shader.fragmentShader = shader.fragmentShader.replace(
        "void main() {",
        `
        varying vec2 vUv;
        uniform vec3 uGlowColor;
        uniform float uGlowIntensity;
        uniform float uGlowRadius;
        uniform vec3 uColor1;
        uniform vec3 uColor2;
        void main() {
        `
      );

      // 替换 gl_FragColor 输出位置，确保在 main 中赋值
      // 通常replace最后的输出句子，在 Three.js ShaderChunk里是 `#include <dithering_fragment>` 或 `#include <output_fragment>`
      // 这里用 #include <dithering_fragment> 作为插入点
      shader.fragmentShader = shader.fragmentShader.replace(
        "#include <dithering_fragment>",
        `
        // 计算中心发光面积，发光距离，光晕强度
        vec2 center = vec2(0.5, 0.5);
        float dist = distance(vUv, center);
        float glowFactor = smoothstep(uGlowRadius, 0.0, dist);
    
        // 结合底色渐变
        vec3 baseGradient = mix(uColor1, uColor2, vUv.y);
    
        // 发光颜色计算
        vec3 glow = uGlowColor * glowFactor * uGlowIntensity;
    
        // 合成最终颜色
        vec3 finalColor = clamp(baseGradient + glow, 0.0, 1.0);
    
        outgoingLight *= finalColor;
    
        gl_FragColor = vec4(outgoingLight, diffuseColor.a);
    
        // 继续执行原始抖动处理
        #include <dithering_fragment>
        `
      );

      // 赋值 uniform 初始值
      shader.uniforms.uGlowColor = { value: new Color(0x2a6e92) };
      shader.uniforms.uGlowIntensity = { value: 0.54 };
      shader.uniforms.uGlowRadius = { value: 0.3 };
      shader.uniforms.uColor1 = { value: new Color(0x2a6e92) };
      shader.uniforms.uColor2 = { value: new Color(0x2a6e92) };
    };

    this.defaultMaterial = faceMaterial;
    this.defaultLightMaterial = this.defaultMaterial.clone();
    this.defaultLightMaterial.color = new Color("rgba(115,208,255,1)");
    this.defaultLightMaterial.opacity = 1;
    this.defaultLightMaterial.emissive.setHex(new Color("rgba(115,208,255,1)"));
    this.defaultLightMaterial.emissiveIntensity = 3.5;
    let mapTop = new BaseMap(this, {
      geoProjectionCenter: this.geoProjectionCenter,
      geoProjectionScale: this.geoProjectionScale,
      position: new Vector3(0, 0, this.depth + 0.22),
      data: mapJsonData,
      material: faceMaterial,
      renderOrder: 2,
    });
    mapTop.mapGroup.children.map((group, index) => {
      group.children.map((mesh) => {
        if (mesh.type === "Mesh") {
          mesh.userData.adcode = "xxx";
          this.eventElement.push(mesh);
        }
      });
    });
    this.mapLineMaterial = new LineBasicMaterial({
      color: 0x4288c7, //省份地图分割线
      opacity: 1,
      transparent: true,
      fog: false,
    });
    let mapLine = new Line(this, {
      geoProjectionCenter: this.geoProjectionCenter,
      geoProjectionScale: this.geoProjectionScale,
      data: mapJsonData,
      material: this.mapLineMaterial,
      // material:glowLineMaterial,
      renderOrder: 3,
    });
    mapLine.lineGroup.position.z += this.depth + 0.23;
    return {
      map,
      mapTop,
      mapLine,
    };
  }
  createProvinceMaterial() {
    let topMaterial = new MeshLambertMaterial({
      // color: 0x276ab3,
      color: 0x2ce2fe,
      transparent: true,
      opacity: 0.8,
      fog: false,
      side: DoubleSide,
    });

    let sideMap = this.assets.instance.getResource("side");
    sideMap.wrapS = RepeatWrapping;
    sideMap.wrapT = RepeatWrapping;
    sideMap.repeat.set(1, 1.5);
    sideMap.offset.y += 0.065;
    let sideMaterial = new MeshStandardMaterial({
      emissive: 0x2ce2fe,
      map: sideMap,
      fog: false,
      opacity: 1,
      side: DoubleSide,
    });
    this.time.on("tick", () => {
      sideMap.offset.y += 0.005;
    });
    sideMaterial.onBeforeCompile = (shader) => {
      shader.uniforms = {
        ...shader.uniforms,
        uColor1: { value: new Color(0x2ce2fe) },
        uColor2: { value: new Color(0x1b5195) },
      };
      shader.vertexShader = shader.vertexShader.replace(
        "void main() {",
        `
        attribute float alpha;
        varying vec3 vPosition;
        varying float vAlpha;
        void main() {
          vAlpha = alpha;
          vPosition = position;
      `
      );
      shader.fragmentShader = shader.fragmentShader.replace(
        "void main() {",
        `
        varying vec3 vPosition;
        varying float vAlpha;
        uniform vec3 uColor1;
        uniform vec3 uColor2;
        void main() {
      `
      );
      shader.fragmentShader = shader.fragmentShader.replace(
        "#include <opaque_fragment>",
        /* glsl */ `
      #ifdef OPAQUE
      diffuseColor.a = 1.0;
      #endif
            #ifdef USE_TRANSMISSION
      diffuseColor.a *= transmissionAlpha + 0.1;
      #endif
      // 三色渐变混合
      vec3 colorA = mix(uColor1, vec3(0.176, 0.580, 0.753), smoothstep(0.0, 0.73, vPosition.z/1.2)); // #2D94C0
      vec3 gradient = mix(colorA, uColor2, smoothstep(0.73, 1.0, vPosition.z/1.2));
      
      outgoingLight = outgoingLight * gradient;
      gl_FragColor = vec4( outgoingLight, diffuseColor.a  );

      
      `
      );
    };
    // vec3 gradient = mix(uColor1, uColor2, vPosition.z/1.2);
    //   outgoingLight = outgoingLight*gradient;
    //   gl_FragColor = vec4( outgoingLight, diffuseColor.a  );
    return [topMaterial, sideMaterial];
  }
  handleProvinceLabelClick(data) {
    console.log("label按下====");
    console.log(data);
  }
  handleLabelMouseDown(data) {
    console.log("label1按下====");
    console.log(data);
  }
  createBar() {
    let self = this;
    let data = sortByValue(this.provincesData).filter(
      (item, index) => index < this.provincesData.length
    );
    const barGroup = new Group();
    this.barGroup = barGroup;
    const factor = 0.2;
    const height = 10.0 * factor;
    const max = 100;
    const maxCount = Math.max(...this.provincesData.map((item) => item.count));
    this.allBar = [];
    this.allBarMaterial = [];
    this.allGuangquan = [];
    this.allProvinceLabel = [];
    this.allProvinceNameLabel = [];
    data.map((item, index) => {
      let geoHeight = height * ((item.count * 100) / maxCount / max);
      let material = new MeshBasicMaterial({
        color: 0xffffff,
        transparent: true,
        opacity: 0,
        depthTest: false,
        fog: false,
      });
      new GradientShader(material, {
        uColor1: 0x50bbfe,
        uColor2: 0x77fbf5,
        size: geoHeight,
        dir: "y",
      });

      // const geo = new BoxGeometry(0.1 * factor, 0.1 * factor, geoHeight)

      // 圆柱参数
      const radiusTop = 0.25 * factor; // 顶部半径
      const radiusBottom = 0.25 * factor; // 底部半径
      const radialSegments = 32; // 圆柱分段数，越高越圆滑
      // 创建圆柱几何体
      const geo = new CylinderGeometry(
        radiusTop,
        radiusBottom,
        geoHeight,
        radialSegments
      );

      // 关键修改：将圆柱旋转90度使其沿Z轴竖立
      geo.rotateX(Math.PI / 2); // 绕X轴旋转90度

      geo.translate(0, 0, geoHeight / 2);
      const mesh = new Mesh(geo, material);
      mesh.renderOrder = 5;
      let areaBar = mesh;
      let [x, y] = this.geoProjection(item.centroid);
      areaBar.position.set(x, -y, this.depth + 0.45);
      areaBar.scale.set(1, 1, 0);
      areaBar.userData = { ...item };
      let guangQuan = this.createQuan(
        new Vector3(x, this.depth + 0.44, y),
        index
      );
      let hg = this.createHUIGUANG(geoHeight, index > 3 ? 0xfffef4 : 0x50c2ff);
      areaBar.add(...hg);
      this.barGroup.add(areaBar);

      let nameLabel = labelNameStyle(
        item,
        index,
        new Vector3(x, -y, this.depth + 0.1)
      );

      this.barGroup.rotation.x = -Math.PI / 2;
      let barLabel = labelStyle04(
        item,
        index,
        new Vector3(x, -y, this.depth + 1.1 + geoHeight)
      );
      this.allBar.push(areaBar);

      this.allProvinceNameLabel.push(nameLabel);
      if (item.count > 0) {
        this.allProvinceLabel.push(barLabel);
        this.allGuangquan.push(guangQuan);
        this.allBarMaterial.push(material);
      }
    });
    this.scene.add(this.barGroup);

    // 省份城市标签
    function labelNameStyle(data, index, position) {
      let label = self.label3d.create("", "provinces-name-label", true);
      label.init(
        `<div class="provinces-name-label"><div class="provinces-name-label-wrap">${data.name}</div></div>`,
        position
      );
      self.label3d.setLabelStyle(label, 0.018, "x");
      label.setParent(self.labelGroup);
      // label.setParent(self.provinceNameGroup)
      label.userData.adcode = data.adcode;
      label.userData.position = [position.x, position.y, position.z];
      return label;
    }
    function labelStyle04(data, index, position) {
      // modify by LING：设置一级文字标签是否自旋转，第三个参数 自旋转false，面向摄像头为true
      let label = self.label3d.create("", "provinces-label", true);
      //   label.init(
      //     `<div class="provinces-label ${index > 4 ? "yellow" : ""}">
      //   <div class="provinces-label-wrap">
      //     <div class="number"><span class="value">${data.value}</span><span class="unit">万人</span></div>
      //     <div class="name">
      //       <span class="zh">${data.name}</span>
      //       <span class="en">${data.enName.toUpperCase()}</span>
      //     </div>
      //     <div class="no">${index + 1}</div>
      //   </div>
      // </div>`),
      label.init(
        `<div class="provinces-label ${
          index > 4 ? "yellow" : ""
        }" style="background: none !important;transform: translateX(-50px);">
      <div class="provinces-label-wrap" style="background: none !important;">
        <div class="number clickable-area"><span class="value">${
          data.count
        }</span><span class="unit">个</span></div>
        <!-- 透明的点击区域覆盖整个标签 -->
        <div class="label-hit-area" 
             style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; 
                    background: transparent; z-index: 2; cursor: pointer;"></div>
      </div>
    </div>`,
        new Vector3(position.x, position.y, position.z)
        // position
      );
      self.label3d.setLabelStyle(label, 0.01, "x");
      label.setParent(self.labelGroup);
      // 记录标签的原始位置
      label.userData.isBillboard = true; // 标记为需要朝向相机
      label.userData.provinceData = data; // 存储关联数据
      label.userData.adcode = data.adcode; // 存储关联数据
      // 获取点击区域DOM元素
      const hitArea = label.element.querySelector(".label-hit-area");
      const clickableElement = label.element.querySelector(".clickable-area");
      clickableElement.addEventListener("mousedown", (event) => {
        event.stopPropagation();
        // 在这里处理点击逻辑
        self.handleProvinceLabelClick(data);
      });

      if (self.interactionManager) {
        // 创建一个透明的平面几何体作为碰撞体
        const hitboxGeometry = new PlaneGeometry(1, 1);
        const hitboxMaterial = new MeshBasicMaterial({
          visible: false,
          transparent: true,
          opacity: 0,
        });
        const hitbox = new Mesh(hitboxGeometry, hitboxMaterial);
        hitbox.position.copy(position);
        hitbox.rotation.x = -Math.PI / 2;
        hitbox.renderOrder = 100;
        hitbox.userData = {
          isLabel: true,
          label: label,
          adcode: data.adcode,
          provinceData: data,
        };

        self.scene.add(hitbox);

        hitbox.addEventListener("mousedown", (event) => {
          self.handleProvinceLabelClick(data);
        });

        // 保存引用以便后续清理
        label.userData.hitbox = hitbox;
      }

      // 添加鼠标事件监听
      hitArea.addEventListener("mousedown", (event) => {
        event.stopPropagation();

        // 创建并派发自定义事件到Three.js场景
        const threeEvent = {
          type: "mousedown",
          target: label,
          data: data,
          stopPropagation: () => {},
          clientX: event.clientX,
          clientY: event.clientY,
        };

        // 调用处理函数
        self.handleLabelMouseDown(threeEvent);
      });
      return label;
    }
  }
  handleSingleClick() {
    console.log("单击事件======");
    this.showTable(4);
  }
  createEvent() {
    let objectsHover = [];
    const reset = (mesh) => {
      mesh.traverse((obj) => {
        if (obj.isMesh) {
          obj.material = this.defaultMaterial;
        }
      });
    };
    const move = (mesh) => {
      mesh.traverse((obj) => {
        if (obj.isMesh) {
          obj.material = this.defaultLightMaterial;
        }
      });
    };
    this.eventElement.map((mesh) => {
      this.interactionManager.add(mesh);
      mesh.addEventListener("mousedown", (ev) => {
        if (this.clicked || !this.mapGroup.visible) return false;

        // 只响应左键点击
        if (event.button !== 0) return;

        this.clickCount++;

        if (this.clickCount === 1) {
          this.clickTimeout = setTimeout(() => {
            this.handleSingleClick(event);
            this.clickCount = 0;
          }, this.doubleClickDelay);
        } else if (this.clickCount === 2) {
          clearTimeout(this.clickTimeout);
          this.clickCount = 0;

          this.clicked = true;
          // console.log(map)
          this.history.push(ev.target.parent.userData);
          this.loadChildMap(ev.target.userData.name);
          this.getProvinceBox(ev.target.userData.name);
        }
      });
      mesh.addEventListener("mouseup", (ev) => {
        this.clicked = false;
      });
      mesh.addEventListener("mouseover", (event) => {
        if (!objectsHover.includes(event.target.parent)) {
          objectsHover.push(event.target.parent);
        }
        document.body.style.cursor = "pointer";
        this.getProvinceBox(event.target.parent.userData.name);
        move(event.target.parent);
      });
      mesh.addEventListener("mouseout", (event) => {
        objectsHover = objectsHover.filter(
          (n) => n.userData.name !== event.target.parent.userData.name
        );
        if (objectsHover.length > 0) {
          const mesh = objectsHover[objectsHover.length - 1];
        }
        reset(event.target.parent);
        document.body.style.cursor = "default";
      });
    });
  }
  createHUIGUANG(h, color) {
    let geometry = new PlaneGeometry(0.35, h);
    geometry.translate(0, h / 2, 0);
    const texture = this.assets.instance.getResource("huiguang");
    texture.colorSpace = SRGBColorSpace;
    texture.wrapS = RepeatWrapping;
    texture.wrapT = RepeatWrapping;
    let material = new MeshBasicMaterial({
      color: color,
      map: texture,
      transparent: true,
      opacity: 0.5,
      depthWrite: false,
      side: DoubleSide,
      blending: AdditiveBlending,
    });
    let mesh = new Mesh(geometry, material);
    mesh.renderOrder = 10;
    mesh.rotateX(Math.PI / 2);
    let mesh2 = mesh.clone();
    let mesh3 = mesh.clone();
    mesh2.rotateY((Math.PI / 180) * 60);
    mesh3.rotateY((Math.PI / 180) * 120);
    return [mesh, mesh2, mesh3];
  }
  createQuan(position, index) {
    const guangquan1 = this.assets.instance.getResource("guangquan1");
    const guangquan2 = this.assets.instance.getResource("guangquan2");
    let geometry = new PlaneGeometry(0.5, 0.5);
    let material1 = new MeshBasicMaterial({
      color: 0xffffff,
      map: guangquan1,
      alphaMap: guangquan1,
      opacity: 1,
      transparent: true,
      depthTest: false,
      fog: false,
      blending: AdditiveBlending,
    });
    let material2 = new MeshBasicMaterial({
      color: 0xffffff,
      map: guangquan2,
      alphaMap: guangquan2,
      opacity: 1,
      transparent: true,
      depthTest: false,
      fog: false,
      blending: AdditiveBlending,
    });
    let mesh1 = new Mesh(geometry, material1);
    let mesh2 = new Mesh(geometry, material2);
    mesh1.renderOrder = 6;
    mesh2.renderOrder = 6;
    mesh1.rotateX(-Math.PI / 2);
    mesh2.rotateX(-Math.PI / 2);
    mesh1.position.copy(position);
    mesh2.position.copy(position);
    mesh2.position.y -= 0.001;
    mesh1.scale.set(0, 0, 0);
    mesh2.scale.set(0, 0, 0);
    this.quanGroup = new Group();
    this.quanGroup.add(mesh1, mesh2);
    this.scene.add(this.quanGroup);
    this.time.on("tick", () => {
      mesh1.rotation.z += 0.05;
    });
    return this.quanGroup;
  }
  // 创建扩散
  createDiffuse() {
    let geometry = new PlaneGeometry(200, 200);
    let material = new MeshBasicMaterial({
      color: 0xffffff,
      depthWrite: false,
      // depthTest: false,
      transparent: true,
      blending: CustomBlending,
    });
    // 使用CustomBlending  实现混合叠加
    material.blendEquation = AddEquation;
    material.blendSrc = DstColorFactor;
    material.blendDst = OneFactor;
    // let diffuse = new DiffuseShader({
    //   material,
    //   time: this.time,
    //   size: 60,
    //   diffuseSpeed: 8.0,
    //   diffuseColor: 0x1a5090,//圆环扩散光
    //   diffuseWidth: 2.0,
    //   callback: (pointShader) => {
    //     setTimeout(() => {
    //       gsap.to(pointShader.uniforms.uTime, {
    //         value: 4,
    //         repeat: -1,
    //         duration: 6,
    //         ease: "power1.easeIn",
    //       })
    //     }, 3)
    //   },
    // })
    let mesh = new Mesh(geometry, material);
    mesh.renderOrder = 3;
    mesh.rotation.x = -Math.PI / 2;
    mesh.position.set(0, 0.21, 0);
    this.scene.add(mesh);
  }
  createGrid() {
    new Grid(this, {
      gridSize: 50,
      gridDivision: 20,
      gridColor: 0x1b4b70,
      shapeSize: 0.5,
      shapeColor: 0x2a5f8a,
      pointSize: 0.1,
      pointColor: 0x154d7d,
    });
  }
  createBottomBg() {
    //底部地图颜色部分
    let geometry = new PlaneGeometry(20, 20);
    const texture = this.assets.instance.getResource("ocean");
    texture.colorSpace = SRGBColorSpace;
    texture.wrapS = RepeatWrapping;
    texture.wrapT = RepeatWrapping;
    texture.repeat.set(1, 1);
    let material = new MeshBasicMaterial({
      map: texture,
      opacity: 1,
      fog: false,
    });
    let mesh = new Mesh(geometry, material);
    mesh.rotation.x = -Math.PI / 2;
    mesh.position.set(0, -0.7, 0);
    // this.scene.add(mesh)
  }
  createChinaBlurLine() {
    let geometry = new PlaneGeometry(147, 147);
    const texture = this.assets.instance.getResource("chinaBlurLine");
    texture.colorSpace = SRGBColorSpace;
    texture.wrapS = RepeatWrapping;
    texture.wrapT = RepeatWrapping;
    texture.generateMipmaps = false;
    texture.minFilter = NearestFilter;
    texture.repeat.set(1, 1);
    let material = new MeshBasicMaterial({
      color: 0x3f82cd,
      alphaMap: texture,
      transparent: true,
      opacity: 1,
    });
    let mesh = new Mesh(geometry, material);
    mesh.rotateX(-Math.PI / 2);
    mesh.position.set(-19.3, -0.5, -19.7);
    //移除中国地图虚影
    // this.scene.add(mesh)
  }

  createLabel() {
    let self = this;
    let label3d = self.label3d;
    let otherLabel = [];
    chinaData.map((province) => {
      if (province.hide == true) return false;
      let label = labelStyle01(province, label3d, self.labelGroup);
      otherLabel.push(label);
    });
    let mapFocusLabel = labelStyle02(
      {
        ...this.mapFocusLabelInfo,
      },
      label3d,
      self.labelGroup
    );
    let iconLabel1 = labelStyle03(
      {
        // icon: labelIcon,
        center: [118.280637, 21.625178],
        width: "40px",
        height: "40px",
        reflect: true,
      },
      label3d,
      self.labelGroup
    );
    let iconLabel2 = labelStyle03(
      {
        // icon: labelIcon,
        center: [106.280637, 25.625178],
        width: "20px",
        height: "20px",
        reflect: false,
      },
      label3d,
      self.labelGroup
    );
    otherLabel.push(mapFocusLabel);
    // otherLabel.push(iconLabel1)
    // otherLabel.push(iconLabel2)
    self.otherLabel = otherLabel;
    function labelStyle01(province, label3d) {
      let label = label3d.create(
        "",
        `china-label ${province.blur ? " blur" : ""}`,
        false
      );
      const [x, y] = self.geoProjection(province.center);
      label.init(
        `<div class="other-label">${province.name}</div>`,
        new Vector3(x, -y, 0.4)
      );
      label3d.setLabelStyle(label, 0.02, "x");
      label.setParent(self.labelGroup);
      return label;
    }
    function labelStyle02(province, label3d) {
      let label = label3d.create("", "map-label", false);
      const [x, y] = self.geoProjection(province.center);
      label.init(
        `<div class="other-label"><span>${province.name}</span><span>${province.enName}</span></div>`,
        new Vector3(x, -y, 0.4)
      );
      label3d.setLabelStyle(label, 0.015, "x");
      label.setParent(self.labelGroup);
      return label;
    }
    function labelStyle03(data, label3d) {
      let label = label3d.create(
        "",
        `decoration-label  ${data.reflect ? " reflect" : ""}`,
        false
      );
      const [x, y] = self.geoProjection(data.center);
      label.init(
        `<div class="other-label"><img class="label-icon" style="width:${data.width};height:${data.height}" src="${data.icon}">`,
        new Vector3(x, -y, 0.4)
      );
      label3d.setLabelStyle(label, 0.02, "x");
      label.setParent(self.labelGroup);
      return label;
    }
    function labelStyle04(data, label3d, index) {
      let label = label3d.create("", "provinces-label", false);
      const [x, y] = self.geoProjection(data.center);
      label.init(
        `<div class="provinces-label">
      <div class="provinces-label-wrap">
        <div class="number">${data.value}<span>万人</span></div>
        <div class="name">
          <span class="zh">${data.name}</span>
          <span class="en">${data.enName.toUpperCase()}</span>
        </div>
        <div class="no">${index + 1}</div>
      </div>
    </div>`,
        new Vector3(x, -y, 2.4)
      );
      label3d.setLabelStyle(label, 0.02, "x");
      label.setParent(self.labelGroup);
      return label;
    }
  }
  createRotateBorder() {
    let max = 12;
    let rotationBorder1 = this.assets.instance.getResource("rotationBorder1");
    let rotationBorder2 = this.assets.instance.getResource("rotationBorder2");
    let plane01 = new Plane(this, {
      width: max * 1.178,
      needRotate: true,
      rotateSpeed: 0.001,
      material: new MeshBasicMaterial({
        map: rotationBorder1,
        color: 0x48afff,
        transparent: true,
        opacity: 1,
        side: DoubleSide,
        depthWrite: false,
        blending: AdditiveBlending,
      }),
      position: new Vector3(0, 0.28, 0),
    });
    plane01.instance.rotation.x = -Math.PI / 2;
    plane01.instance.renderOrder = 6;
    plane01.instance.scale.set(0, 0, 0);
    plane01.setParent(this.scene);
    let plane02 = new Plane(this, {
      width: max * 1.116,
      needRotate: true,
      rotateSpeed: -0.004,
      material: new MeshBasicMaterial({
        map: rotationBorder2,
        color: 0x48afff,
        transparent: true,
        opacity: 1,
        side: DoubleSide,
        depthWrite: false,
        blending: AdditiveBlending,
      }),
      position: new Vector3(0, 0.3, 0),
    });
    plane02.instance.rotation.x = -Math.PI / 2;
    plane02.instance.renderOrder = 6;
    plane02.instance.scale.set(0, 0, 0);
    plane02.setParent(this.scene);
    this.rotateBorder1 = plane01.instance;
    this.rotateBorder2 = plane02.instance;// 保留Z轴旋转动画
    
  }
  createFlyLine() {
    this.flyLineGroup = new Group();
    this.flyLineGroup.visible = false;
    this.scene.add(this.flyLineGroup);
    const texture = this.assets.instance.getResource("mapFlyline");
    texture.wrapS = texture.wrapT = RepeatWrapping;
    texture.repeat.set(0.5, 2);
    const tubeRadius = 0.1;
    const tubeSegments = 32;
    const tubeRadialSegments = 2;
    const closed = false;
    let [centerX, centerY] = this.geoProjection(this.flyLineCenter);
    let centerPoint = new Vector3(centerX, -centerY, 0);
    const material = new MeshBasicMaterial({
      map: texture,
      // alphaMap: texture,
      color: 0x50c2ff,
      transparent: true,
      fog: false,
      opacity: 1,
      depthTest: false,
      blending: AdditiveBlending,
    });
    this.time.on("tick", () => {
      texture.offset.x -= 0.006;
    });
    this.provincesData
      .filter((item, index) => index < this.provincesData.length)
      .map((city) => {
        if (city.count <= 0) {
          return;
        }
        let [x, y] = this.geoProjection(city.centroid);
        let point = new Vector3(x, -y, 0);
        const center = new Vector3();
        center.addVectors(centerPoint, point).multiplyScalar(0.5);
        center.setZ(3);
        const curve = new QuadraticBezierCurve3(centerPoint, center, point);
        const tubeGeometry = new TubeGeometry(
          curve,
          tubeSegments,
          tubeRadius,
          tubeRadialSegments,
          closed
        );
        const mesh = new Mesh(tubeGeometry, material);
        mesh.rotation.x = -Math.PI / 2;
        mesh.position.set(0, this.depth + 0.44, 0);
        mesh.renderOrder = 21;
        this.flyLineGroup.add(mesh);
      });
  }
  // 创建焦点
  createFocus() {
    let focusObj = new Focus(this, { color1: 0x50c2ff, color2: 0x50c2ff });
    let [x, y] = this.geoProjection(this.flyLineCenter);
    focusObj.position.set(x, -y, this.depth + 0.44);
    focusObj.scale.set(1, 1, 1);
    this.flyLineFocusGroup.add(focusObj);
  }
  // 创建粒子
  createParticles() {
    this.particles = new Particles(this, {
      num: 10,
      range: 30,
      dir: "up",
      speed: 0.05,
      material: new PointsMaterial({
        map: Particles.createTexture(),
        size: 1,
        color: 0x50c2ff,
        transparent: true,
        opacity: 1,
        depthTest: false,
        depthWrite: false,
        vertexColors: true,
        blending: AdditiveBlending,
        sizeAttenuation: true,
      }),
    });
    this.particleGroup = new Group();
    this.scene.add(this.particleGroup);
    this.particleGroup.rotation.x = -Math.PI / 2;
    this.particles.setParent(this.particleGroup);
    this.particles.enable = true;
    this.particleGroup.visible = true;
  }
  createScatter() {
    this.scatterGroup = new Group();
    this.scatterGroup.visible = false;
    this.scatterGroup.rotation.x = -Math.PI / 2;
    this.scene.add(this.scatterGroup);
    const texture = this.assets.instance.getResource("arrow");
    const material = new SpriteMaterial({
      map: texture,
      color: 0xfffef4,
      fog: false,
      transparent: true,
      depthTest: false,
    });
    let scatterAllData = sortByValue(scatterData);
    let max = scatterAllData[0].value;
    scatterAllData.map((data) => {
      const sprite = new Sprite(material);
      sprite.renderOrder = 23;
      let scale = 0.1 + (data.value / max) * 0.2;
      sprite.scale.set(scale, scale, scale);
      let [x, y] = this.geoProjection([data.lng, data.lat]);
      sprite.position.set(x, -y, this.depth + 0.45);
      sprite.userData.position = [x, -y, this.depth + 0.45];
      this.scatterGroup.add(sprite);
    });
  }
  createInfoPoint() {
    let self = this;
    this.InfoPointGroup = new Group();
    this.scene.add(this.InfoPointGroup);
    this.InfoPointGroup.visible = false;
    this.InfoPointGroup.rotation.x = -Math.PI / 2;
    this.infoPointIndex = 0;
    this.infoPointLabelTime = null;
    this.infoLabelElement = [];
    let label3d = this.label3d;
    const texture = this.assets.instance.getResource("point");
    let colors = [0xfffef4, 0x50c2ff];
    let infoAllData = sortByValue(infoData);
    let max = infoAllData[0].value;
    infoAllData.map((data, index) => {
      const material = new SpriteMaterial({
        map: texture,
        color: colors[index % colors.length],
        fog: false,
        transparent: true,
        depthTest: false,
      });
      const sprite = new Sprite(material);
      sprite.renderOrder = 23;
      let scale = 0.7 + (data.value / max) * 0.4;
      sprite.scale.set(scale, scale, scale);
      let [x, y] = this.geoProjection([data.lng, data.lat]);
      let position = [x, -y, this.depth + 0.7];
      sprite.position.set(...position);
      sprite.userData.position = [...position];
      sprite.userData = {
        position: [x, -y, this.depth + 0.7],
        name: data.name,
        value: data.value,
        level: data.level,
        index: index,
      };
      this.InfoPointGroup.add(sprite);
      let label = infoLabel(data, label3d, this.InfoPointGroup);
      this.infoLabelElement.push(label);
      this.interactionManager.add(sprite);
      sprite.addEventListener("mousedown", (ev) => {
        if (this.clicked || !this.InfoPointGroup.visible) return false;
        this.clicked = true;
        this.infoPointIndex = ev.target.userData.index;
        this.infoLabelElement.map((label) => {
          label.visible = false;
        });
        label.visible = true;
        // this.createInfoPointLabelLoop()
      });
      sprite.addEventListener("mouseup", (ev) => {
        this.clicked = false;
      });
      sprite.addEventListener("mouseover", (event) => {
        document.body.style.cursor = "pointer";
      });
      sprite.addEventListener("mouseout", (event) => {
        document.body.style.cursor = "default";
      });
    });
    function infoLabel(data, label3d, labelGroup) {
      let label = label3d.create("", "info-point", true);
      const [x, y] = self.geoProjection([data.lng, data.lat]);
      label.init(
        ` <div class="info-point-wrap">
          <div class="info-point-wrap-inner">
            <div class="info-point-line">
              <div class="line"></div>
              <div class="line"></div>
              <div class="line"></div>
            </div>
            <div class="info-point-content">
              <div class="content-item"><span class="label">名称</span><span class="value">${data.name}</span></div>
              <div class="content-item"><span class="label">PM2.5</span><span class="value">${data.value}ug/m²</span></div>
              <div class="content-item"><span class="label">等级</span><span class="value">${data.level}</span></div>
            </div>
          </div>
        </div>
      `,
        new Vector3(x, -y, self.depth + 1.9)
      );
      label3d.setLabelStyle(label, 0.015, "x");
      label.setParent(labelGroup);
      label.visible = false;
      return label;
    }
  }
  createInfoPointLabelLoop() {
    clearInterval(this.infoPointLabelTime);
    this.infoPointLabelTime = setInterval(() => {
      this.infoPointIndex++;
      if (this.infoPointIndex >= this.infoLabelElement.length) {
        this.infoPointIndex = 0;
      }
      this.infoLabelElement.map((label, i) => {
        if (this.infoPointIndex === i) {
          label.visible = true;
        } else {
          label.visible = false;
        }
      });
    }, 3000);
  }
  createStorke() {
    const mapStroke = this.assets.instance.getResource("mapStroke");
    const texture = this.assets.instance.getResource("pathLine3");
    texture.wrapS = texture.wrapT = RepeatWrapping;
    texture.repeat.set(2, 1);

    let pathLine = new Line(this, {
      geoProjectionCenter: this.geoProjectionCenter,
      geoProjectionScale: this.geoProjectionScale,
      position: new Vector3(0, 0, this.depth + 0.24),
      data: mapStroke,
      material: new MeshBasicMaterial({
        color: 0x000000,
        map: texture,
        alphaMap: texture,
        fog: false,
        transparent: true,
        opacity: 1,
        blending: AdditiveBlending,
      }),
      type: "Line3",
      renderOrder: 22,
      tubeRadius: 0.03,
    });
    // 设置父级
    this.focusMapGroup.add(pathLine.lineGroup);
    this.time.on("tick", () => {
      texture.offset.x += 0.005;
    });
  }

  geoProjection(args) {
    return geoMercator()
      .center(this.geoProjectionCenter)
      .scale(this.geoProjectionScale)
      .translate([0, 0])(args);
  }
  update() {
    super.update();
    this.interactionManager && this.interactionManager.update();
    // 更新标签朝向
    if (this.labelGroup) {
      this.labelGroup.children.forEach((label) => {
        if (label.userData.isBillboard) {
          // 使标签始终朝向相机
          label.lookAt(this.camera.instance.position);
        }
      });
    }
  }
  destroy() {
    super.destroy();
    this.label3d && this.label3d.destroy();
  }
}
